﻿using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Reflection;
using XLib.Base;
using XLib.Base.Ex;
using XLib.Base.VirtualDisk;
using XLib.Node;
using XNode.SubSystem.NodeEditSystem.Control;
using XNode.SubSystem.NodeLibSystem.Define.Data;
using XNode.SubSystem.NodeLibSystem.Define.Drivers;
using XNode.SubSystem.NodeLibSystem.Define.Events;
using XNode.SubSystem.NodeLibSystem.Define.Flows;
using XNode.SubSystem.NodeLibSystem.Define.Functions;
using XNode.SubSystem.OptionSystem;

namespace XNode.SubSystem.NodeLibSystem
{
    public class NodeLibManager : IManager
    {
        #region 单例

        private NodeLibManager() { }
        public static NodeLibManager Instance { get; } = new NodeLibManager();

        #endregion

        #region 属性

        #endregion

        #region IManager 方法

        public void Init()
        {
            BuildInnerNodeLib();
            LoadOutsideNodeLib();
        }

        public void Reset() { }

        public void Clear() { }

        #endregion

        #region 公开方法

        #endregion

        #region 私有方法


        /// <summary>
        /// 构建内置节点库
        /// </summary>
        private void BuildInnerNodeLib()
        {
            //注册pingroup和pingroupview
            NodeFactory.Ins.RegisterPinGroupPair<ExecutePinGroup, ExecutePinGroupView>();
            NodeFactory.Ins.RegisterPinGroupPair<DataPinGroup, DataPinGroupView>();
            NodeFactory.Ins.RegisterPinGroupPair<ActionPinGroup, ActionPinGroupView>();
            NodeFactory.Ins.RegisterPinGroupPair<ControlPinGroup, ControlPinGroupView>();

            NodeFactory.Ins.RegisterNode<Data_Int>(NodeConstNames.InnerNodeName, NodeConstNames.DriveNodeName, "");
            NodeFactory.Ins.RegisterNode<Data_Double>(NodeConstNames.InnerNodeName, NodeConstNames.DriveNodeName, "");
            NodeFactory.Ins.RegisterNode<Data_String>(NodeConstNames.InnerNodeName, NodeConstNames.DriveNodeName, "");

            NodeFactory.Ins.RegisterNode<FrameDriver>(NodeConstNames.InnerNodeName, NodeConstNames.DriveNodeName, "");
            NodeFactory.Ins.RegisterNode<TimerDriver>(NodeConstNames.InnerNodeName, NodeConstNames.DriveNodeName, "");

            NodeFactory.Ins.RegisterNode<Event_Keyboard>(NodeConstNames.InnerNodeName, NodeConstNames.EventNodeName, "");

            NodeFactory.Ins.RegisterNode<Func_Compare>(NodeConstNames.InnerNodeName, NodeConstNames.FuncNodeName, NodeConstNames.ComputeFuncsName);
            NodeFactory.Ins.RegisterNode<Func_RatioToInt>(NodeConstNames.InnerNodeName, NodeConstNames.FuncNodeName, NodeConstNames.ConvertersName);
            NodeFactory.Ins.RegisterNode<Func_NumberToRatio>(NodeConstNames.InnerNodeName, NodeConstNames.FuncNodeName, NodeConstNames.ConvertersName);
            NodeFactory.Ins.RegisterNode<Func_SendNetMessage>(NodeConstNames.InnerNodeName, NodeConstNames.FuncNodeName, "");
            NodeFactory.Ins.RegisterNode<Func_Log>(NodeConstNames.InnerNodeName, NodeConstNames.FuncNodeName, "");

            NodeFactory.Ins.RegisterNode<Func_CreateThread>(NodeConstNames.InnerNodeName, NodeConstNames.FuncNodeName, NodeConstNames.ExecControlName);
            NodeFactory.Ins.RegisterNode<Func_Delay>(NodeConstNames.InnerNodeName, NodeConstNames.FuncNodeName, NodeConstNames.ExecControlName);
            NodeFactory.Ins.RegisterNode<Func_Sleep>(NodeConstNames.InnerNodeName, NodeConstNames.FuncNodeName, NodeConstNames.ExecControlName);

            NodeFactory.Ins.RegisterNode<Flow_If>(NodeConstNames.InnerNodeName, NodeConstNames.FlowNodeName, "");
            NodeFactory.Ins.RegisterNode<Flow_LoopByCount>(NodeConstNames.InnerNodeName, NodeConstNames.FlowNodeName, "");
            NodeFactory.Ins.RegisterNode<Flow_While>(NodeConstNames.InnerNodeName, NodeConstNames.FlowNodeName, "");
            NodeFactory.Ins.RegisterNode<Flow_Switch>(NodeConstNames.InnerNodeName, NodeConstNames.FlowNodeName, "");



        }

        /// <summary>
        /// 加载外部节点库
        /// </summary>
        private void LoadOutsideNodeLib()
        {
            var NodeLibDict = new Dictionary<string, INodeLib>();
            // 遍历节点库文件
            foreach (var dllPath in GetAllNodeLibDll())
            {
                // 加载动态库
                Assembly dll = Assembly.LoadFrom(dllPath);
                // 遍历全部类
                foreach (var type in dll.GetTypes())
                {
                    if (typeof(INodeLib).IsAssignableFrom(type))
                    {
                        // 获取单例
                        PropertyInfo? propertyInfo = type.GetProperty("Instance");
                        if (propertyInfo == null) continue;
                        if (propertyInfo.GetValue(null) is not INodeLib instance) continue;
                        // 初始化单例
                        instance.Init(NodeFactory.Ins);
                        // 保存引用
                        NodeLibDict.Add(instance.Name, instance);
                    }
                }
            }
            // 遍历节点库
            //foreach (var libPair in NodeLibDict)
            //{
            //    // 创建根文件夹
            //    Folder root = NodeFactory.Ins.LibHarddisk.CreateFolder(libPair.Value.Title.PackToList());
            //    // 加载文件夹
            //    LoadFolder(root, NodeFactory.Ins.LibHarddisk.Root);
            //}
        }

        /// <summary>
        /// 获取全部节点库文件
        /// </summary>
        private List<string> GetAllNodeLibDll()
        {
            string nodepath = OptionManager.Instance.NodeLibPath;
            if (!Directory.Exists(OptionManager.Instance.NodeLibPath))
            {
                //create the directory
                Directory.CreateDirectory(OptionManager.Instance.NodeLibPath);
            }
            if (!Directory.Exists(OptionManager.Instance.NodeLibPath)) return new List<string>();

            DirectoryInfo directoryInfo = new DirectoryInfo(OptionManager.Instance.NodeLibPath);
            List<string> result = new List<string>();
            foreach (var fileInfo in directoryInfo.GetFiles())
            {
                if (fileInfo.Extension == ".dll") result.Add(fileInfo.FullName);
            }
            return result;
        }

        /// <summary>
        /// 加载文件夹至目标文件夹
        /// </summary>
        private void LoadFolder(Folder target, Folder oldFolder)
        {
            // 加载文件夹
            foreach (var oldChild in oldFolder.FolderList)
            {
                // 创建子文件夹
                Folder childFolder = new Folder(oldChild.Name, target);
                // 添加子文件夹
                target.FolderList.Add(childFolder);
                // 递归加载
                LoadFolder(childFolder, oldChild);
            }
            // 加载文件
            foreach (var oldFile in oldFolder.FileList)
            {
                // 创建文件
                NodeFactory.Ins.LibHarddisk.CreateFile(target, oldFile.Name, oldFile.Extension, oldFile.Instance);
            }
        }

        #endregion

        #region 字段

        #endregion
    }
}